<div class="tmd-doc">
<p></p>
<h1 class="tmd-header-1">
GoTV
</h1>
<p></p>
<div class="tmd-usual">
<span class="tmd-bold"><span class="tmd-italic">GoTV</span></span> is a tool used to manage and use multiple coexisting installations of official Go toolchain versions harmoniously and conveniently. The name is an abbreviation of <span class="tmd-bold">Go</span> <span class="tmd-bold">T</span>oolchain <span class="tmd-bold">V</span>ersion.
</div>
<p></p>
<div class="tmd-usual">
Project page: <a href="https://github.com/go101/gotv">https://github.com/go101/gotv</a>
</div>
<p></p>
<div class="tmd-usual">
Please follow <a href="https://twitter.com/zigo_101">@zigo_101</a> to get the latest news of GoTV (and all kinds of Go details/facts/tips/...).
</div>
<p></p>
<p></p>
<h2 class="tmd-header-2">
Installation
</h2>
<p></p>
<div class="tmd-usual">
Run
</div>
<p></p>
<pre class="tmd-code">
go install go101.org/gotv@latest
</pre>
<p></p>
<div class="tmd-usual">
to install <span class="tmd-bold"><span class="tmd-italic">GoTV</span></span>.
</div>
<p></p>
<div class="tmd-usual">
A 1.17+ toolchain version is needed to finish the installation. The toolchain version may be uninstalled after pinning a suitable toolchain version (see below).
</div>
<p></p>
<h2 class="tmd-header-2">
Usage
</h2>
<p></p>
<div class="tmd-usual">
Run <code class="tmd-code-span">gotv</code> without any arguments to show help messages.
</div>
<p></p>
<div class="tmd-usual">
Most <code class="tmd-code-span">gotv</code> commands are in the following format:
</div>
<p></p>
<pre class="tmd-code">
gotv ToolchainVersion [go-arguments...]
</pre>
<p></p>
<div class="tmd-usual">
During running the first such a command, the Go git repository will be cloned (which needs several minutes to finish).
</div>
<p></p>
<div class="tmd-usual">
<code class="tmd-code-span">ToolchainVersion</code> might be
</div>
<p></p>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
a Go release version, such as <code class="tmd-code-span">1.17.13</code>, <code class="tmd-code-span">1.18</code>, <code class="tmd-code-span">1.19rc1</code>, which mean the release tags <code class="tmd-code-span">go1.17.13</code>, <code class="tmd-code-span">go1.18</code>, <code class="tmd-code-span">go1.19rc1</code>, respectively, in the Go git repository. Note:
</div>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
<code class="tmd-code-span">1.N.</code> means the latest release of <code class="tmd-code-span">1.N</code> (since Go toolchain 1.21, <code class="tmd-code-span">1.N</code> also means the latest release of <code class="tmd-code-span">1.N</code>).
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
<code class="tmd-code-span">1.</code> means the latest Go 1 release version.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
<code class="tmd-code-span">.</code> means the latest Go release version.
</div>
</li>
</ul>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
<code class="tmd-code-span">:1.N</code>, which means the local latest <code class="tmd-code-span">release-branch.go1.N</code> branch in the Go git repository.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
<code class="tmd-code-span">:tip</code>, which means the local latest <code class="tmd-code-span">master</code> branch in the Go git repository.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
a version suffixed with <code class="tmd-code-span">!</code> means to fetch remote versions (by running <code class="tmd-code-span">gotv fetch-versions</code>) firstly.
</div>
</li>
</ul>
<p></p>
<div class="tmd-usual">
Examples:
</div>
<p></p>
<pre class="tmd-code">
$ gotv 1.17. version
[Run]: $HOME/.cache/gotv/tag_go1.17.13/bin/go version
go version go1.17.13 linux/amd64

$ gotv 1.18.3 version
[Run]: $HOME/.cache/gotv/tag_go1.18.3/bin/go version
go version go1.18.3 linux/amd64

$ cat search.go
package main

import "fmt"

func demoFilter(n int) bool {
	return n &amp; 1 == 0;
}

// Search values and return them without perverting order.
func search(start, end int)(r []int) {
	var count = 0
	for i, index := start, 0; i &lt;= end; i++ {
		if demoFilter(i) {
			count++
			defer func(value int) {
				r[index] = value
				index++
			}(i)
		}
	}

	r = make([]int, count) // only allocate once
	return
}

func main() {
	fmt.Println(search(0, 9))
}

$ gotv 1.21 run search.go
[Run]: $HOME/.cache/gotv/tag_go1.21.7/bin/go run search.go
[8 6 4 2 0]
$ gotv 1.22 run search.go
[Run]: $HOME/.cache/gotv/tag_go1.22.1/bin/go run search.go
[0 0 0 0 0]
</pre>
<p></p>
<div class="tmd-usual">
<span class="tmd-italic">(The example code comes from </span><a href="https://go101.org/blog/2024-03-01-for-loop-semantic-changes-in-go-1.22.html"><span class="tmd-italic">this blog article</span></a><span class="tmd-italic">. More uses of GoTV are demonstrated </span><a href="https://go101.org/blog/2022-08-22-some-undocumented-changes-in-go-1.18-and-1.19.html"><span class="tmd-italic">here</span></a><span class="tmd-italic">.)</span>
</div>
<p></p>
<p></p>
<div class="tmd-usual">
All <code class="tmd-code-span">gotv</code> specific commands:
</div>
<p></p>
<pre class="tmd-code">
# sync the local Go git repository with remote
gotv fetch-versions

# list all versions seen locally
gotv list-versions

# build and cache some toolchain versions
gotv cache-version ToolchainVersion [ToolchainVersion ...]

# uncache some toolchain versions to save disk space
gotv uncache-version ToolchainVersion [ToolchainVersion ...]

# pin a specified toolchain version at a stable path
gotv pin-version ToolchainVersion

# unpin the current pinned toolchain version
gotv unpin-version

# set the default toolchain version (since v0.2.1)
gotv default-version ToolchainVersion

# check the default toolchain version (since v0.2.1)
gotv default-version
</pre>
<p></p>
<h2 class="tmd-header-2">
Pin a toolchain version
</h2>
<p></p>
<div class="tmd-usual">
We can use the <code class="tmd-code-span">gotv pin-version</code> command to pin a specific toolchain version to a stable path. After adding the stable path to the <code class="tmd-code-span">PATH</code> environment veriable, we can use the official <code class="tmd-code-span">go</code> command directly. And after doing these, the toolchain versions installed through ways other than GoTV may be safely uninstalled.
</div>
<p></p>
<div class="tmd-usual">
It is recommended to pin a 1.17+ version for <a href="https://github.com/golang/go/issues/44505">bootstrap purpose</a> now. The following example shows how to pin Go toolchain version 1.17.13:
</div>
<p></p>
<p></p>
<pre class="tmd-code">
$ gotv pin-version 1.17.
[Run]: cp -r $HOME/.cache/gotv/tag_go1.17.13 $HOME/.cache/gotv/pinned-toolchain

Please put the following shown pinned toolchain path in
your PATH environment variable to use go commands directly:

	/home/username/.cache/gotv/pinned-toolchain/bin
</pre>
<p></p>
<div class="tmd-usual">
After the prompted path is added to the PATH environment variable, open a new terminal window:
</div>
<p></p>
<pre class="tmd-code">
$ go version
go version go1.17.13 linux/amd64
</pre>
<p></p>
<div class="tmd-usual">
The command <code class="tmd-code-span">gotv pin-version .!</code> will upgrade the pinned toolchain to the latest release version (which may be a beta or rc version).
</div>
<p></p>
<h2 class="tmd-header-2">
Set a bootstrap toolchain version
</h2>
<p></p>
<div class="tmd-usual">
To build a toolchain verision, another already built toolchain version is needed to be used in the building process. The other toolchain version is called the bootstrap version.
</div>
<p></p>
<div class="tmd-usual">
Some facts:
</div>
<p></p>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
Toolchain versions &lt;= 1.12.17 are unable to be built with toochain versions &gt;= 1.16;
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
Toolchain versions &lt;= 1.5.4 are uanable to be built with toolchain versions &gt;= 1.6;
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
<a href="https://github.com/golang/go/issues/44505">A 1.17.13+ toolchain version is required to build 1.20+ toolchain versions</a>;
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
<a href="https://github.com/golang/go/issues/54265">A 1.20.14+ toolchain version is required to build 1.22+ toolchain versions</a>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
<a href="https://github.com/golang/go/issues/64751">A 1.22.6+ toolchain version is required to build 1.24+ toolchain versions</a>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
<a href="https://github.com/golang/go/issues/69315">A 1.24.0+ toolchain version is required to build 1.26+ toolchain versions</a>.
</div>
</li>
</ul>
<p></p>
<p></p>
<div class="tmd-usual">
Currently, GoTV uses the toolchain set in the <code class="tmd-code-span">PATH</code> environment variable as the bootstrap version by default. If <code class="tmd-code-span">GOROOT_BOOTSTRAP</code> environment variable is set, then its value will be used.
</div>
<p></p>
</div>
